# encoding: utf-8
# @File  : cron_processor.py
# @Author: shaoyun
# @Date  :  2025/05/11

import asyncio
import json
from datetime import datetime
from croniter import croniter
from loguru import logger
from sqlalchemy.orm import Session

from app.models.task import Task, TaskStatus
from app.services.task_scheduler import TaskScheduler
from app.db.mysql import SessionLocal


class CronProcessor:
    """定时任务处理器"""

    @staticmethod
    async def run_cron_loop():
        """运行定时任务检查循环"""
        logger.info("Starting cron processor...")

        while True:
            try:
                db = SessionLocal()
                await CronProcessor.process_cron_tasks(db)
                db.close()

                # 每分钟检查一次
                await asyncio.sleep(60)

            except Exception as e:
                logger.error(f"Error in cron loop: {e}")
                await asyncio.sleep(10)

    @staticmethod
    async def process_cron_tasks(db: Session):
        """处理定时任务"""
        now = datetime.utcnow()

        # 获取所有定时任务
        cron_tasks = db.query(Task).filter(
            Task.cron.isnot(None),
            Task.status.in_([TaskStatus.PENDING, TaskStatus.COMPLETED])
        ).all()

        for task in cron_tasks:
            try:
                # 验证cron表达式
                if not croniter.is_valid(task.cron):
                    logger.warning(f"Invalid cron expression for task {task.id}: {task.cron}")
                    continue

                # 计算下次执行时间
                base_time = task.finished_at if task.finished_at else task.created_at
                cron = croniter(task.cron, base_time)
                next_run = cron.get_next(datetime)

                # 如果到了执行时间
                if next_run <= now:
                    logger.info(f"Triggering cron task {task.id}")

                    # 创建新的任务实例
                    new_task = await TaskScheduler.create_task(
                        db=db,
                        user_id=task.user_id,
                        spider_id=task.spider_id,
                        name=f"{task.name} (定时执行)",
                        parameters=json.loads(task.parameters) if task.parameters else {},
                        priority=task.priority,
                        cron=None  # 新任务不是定时任务
                    )

                    logger.info(f"Created new task {new_task.id} from cron task {task.id}")

            except Exception as e:
                logger.error(f"Error processing cron task {task.id}: {e}")